package com.link.base.base.mptmpl.service;

import com.link.base.base.mptmpl.dao.mybatis.mapper.MpTmplMapper;
import com.link.base.base.mptmpl.model.MpTmpl;
import com.link.base.base.mptmpl.model.MpTmplRule;
import com.link.base.tencent.corpwx.usertag.model.UserTagItem;
import com.link.base.tencent.corpwx.usertag.service.UserTagItemService;
import com.link.base.user.model.CoreUser;
import com.link.core.basic.dao.mapper.BasicMapper;
import com.link.core.basic.service.BasicServiceImpl;
import com.link.core.basic.service.ServiceException;
import com.link.core.util.JsonUtil;
import com.link.core.util.RedisUtil;
import com.link.core.util.StringUtils;
import com.link.core.util.UserUtil;
import com.link.core.util.redisclient.LinkRedisClient;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Set;

/**
 * 小程序页面模板配置
 *
 * @author 黄安邦
 * @date 2020-07-02 18:27:01
 */
@Service
public class MpTmplServiceImpl extends BasicServiceImpl<MpTmpl> implements MpTmplService {
    /**
     * 模板缓存key前缀，${LOV_REDIS_PREFIX}#${type}#${username} 构成缓存key
     */
    private static final String TMPL_CACHE_PREFIX = "MP_TEMPLATE_CACHE";
    /**
     * 模板缓存失效时间，秒
     */
    private static final int CACHE_EXPIRE_TIME = 60 * 60 * 24 * 3;
    @Resource
    private MpTmplRuleService mpTmplRuleService;
    @Resource
    private UserTagItemService userTagItemService;
    @Resource
    private MpTmplMapper mpTmplMapper;

    @Override
    public BasicMapper<MpTmpl> getBasicMapper() {
        return mpTmplMapper;
    }

    @Override
    public String getTmplByRule(MpTmpl example) throws Exception {
        if (StringUtils.isBlank(example.getType())) {
            throw new ServiceException("请指定模板类型");
        }
        // 1、先检查缓存，若缓存没有数据再往下执行，有则直接返回缓存数据
        String result = getTmplFromCache(example);
        if ("null".equals(result)) {
            return null;
        } else if (result != null) {
            return result;
        }
        // 2、查询所有符合条件的模板
        List<MpTmpl> tmplList = mpTmplMapper.queryByExamplePage(example);

        // 3、循环遍历获取到的模板列表
        MpTmplRule ruleExample = new MpTmplRule();
        ruleExample.setRows(2000);
        for (int i = 0, len = tmplList != null ? tmplList.size() : 0; i < len; i++) {
            MpTmpl tmplItem = tmplList.get(i);

            // 4、查询当前模板所有的规则
            ruleExample.setTmplId(tmplItem.getId());
            List<MpTmplRule> ruleList = mpTmplRuleService.queryByExamplePage(ruleExample);

            // 5、遍历规则列表，分别对组织、标签、职责、用户类型做不同处理，检查当前用户是否包含在规则中
            boolean match = checkUserMatchRules(ruleList);

            // 6、若用户在规则中，设置缓存并返回当前模板；若不在则返回第三步
            if (match) {
                result = setTmpl2Cache(tmplItem);
                return result;
            }
        }
        // 7、无符合条件模板，返回null，并设置缓存为null
        MpTmpl tmpl = new MpTmpl();
        tmpl.setType(example.getType());
        tmpl.setId(null);
        setTmpl2Cache(tmpl);
        return null;
    }

    @Override
    public void clearCacheByType(String type) {
        LinkRedisClient jedis = null;
        try {
            jedis = RedisUtil.getJedis();
            String pattern = TMPL_CACHE_PREFIX + "#" + type + "#*";
            Set<String> keySet = jedis.keys(pattern);
            jedis.del(keySet);
        } catch (Exception e) {
            throw new ServiceException("清除缓存发生错误：" + e.getMessage());
        } finally {
            RedisUtil.returnResource(jedis);
        }
    }

    /**
     * 从缓存中获取模板配置
     *
     * @author 姚润发
     * @param example
     * @return
     * @date 2020/7/29 11:16
     */
    private String getTmplFromCache(MpTmpl example) {
        LinkRedisClient jedis = null;
        try {
            jedis = RedisUtil.getJedis();
            CoreUser user = UserUtil.getUser();
            String key = TMPL_CACHE_PREFIX + "#" + example.getType() + "#" + user.getUsername();
            // 如果缓存存在则获取缓存数据并重设过期时间
            if (jedis.exists(key)) {
                String value = jedis.get(key);
                jedis.expire(key, CACHE_EXPIRE_TIME);
                return value;
            }
            return null;
        } catch (Exception e) {
            throw new ServiceException("获取缓存错误：" + e.getMessage());
        } finally {
            RedisUtil.returnResource(jedis);
        }
    }

    /**
     * 设置模板到缓存中，并返回Json字符串
     * @author 姚润发
     * @param tmpl
     * @return
     * @date 2020/7/29 15:36
     */
    private String setTmpl2Cache(MpTmpl tmpl) {
        LinkRedisClient jedis = null;
        try {
            jedis = RedisUtil.getJedis();
            CoreUser user = UserUtil.getUser();
            String key = TMPL_CACHE_PREFIX + "#" + tmpl.getType() + "#" + user.getUsername();
            String value = JsonUtil.toString(tmpl);
            if (tmpl.getId() == null) {
                value = "null";
            }
            jedis.set(key, value);
            jedis.expire(key, CACHE_EXPIRE_TIME);
            return value;
        } catch (Exception e) {
            throw new ServiceException("设置缓存发生错误：" + e.getMessage());
        } finally {
            RedisUtil.returnResource(jedis);
        }
    }

    /**
     * 检查当前用户是否符合模板规则要求
     *
     * @author 姚润发
     * @param ruleList
     * @return
     * @date 2020/7/29 15:25
     */
    private boolean checkUserMatchRules(List<MpTmplRule> ruleList) throws Exception {
        int len = ruleList != null ? ruleList.size() : 0;
        CoreUser user = UserUtil.getUser();
        // 当前登录用户组织ID
        Long userOrgId = user.getOrgId() == null ? -1L : user.getOrgId();
        // 当前登录用户部门ID
        Long userDeptId = user.getDeptId() == null ? -1L : user.getDeptId();
        // 当前登录用户的app职责ID
        Long userAppRespId = user.getAppRespId() == null ? -1L : user.getAppRespId();

        for (int i = 0; i < len; i++) {
            MpTmplRule ruleItem = ruleList.get(i);
            switch (ruleItem.getRuleType()) {
                // 组织类型
                case "Org":
                    if (userOrgId.equals(ruleItem.getOrgId())
                            || userDeptId.equals(ruleItem.getOrgId())) {
                        return true;
                    }
                    break;
                // 职责类型
                case "Duty":
                    if (userAppRespId.equals(ruleItem.getDutyId())) {
                        return true;
                    }
                    break;
                // 用户类型
                case "User":
                    if (user.getUsername().equals(ruleItem.getUserNum())) {
                        return true;
                    }
                    break;
                case "Tag":
                    UserTagItem tagItemExample = new UserTagItem();
                    tagItemExample.setHeadId(ruleItem.getTagId());
                    tagItemExample.setUsername(user.getUsername());
                    List<UserTagItem> list = userTagItemService.queryByExamplePage(tagItemExample);
                    if (list != null && list.size() > 0) {
                        return true;
                    }
                    break;
                default:
            }
        }
        return false;
    }
}
